home *** CD-ROM | disk | FTP | other *** search
/ Software of the Month Club 1996 April / Software of the Month Club 1996 April.iso / pc / os2 / psutils / src / psselect.c < prev    next >
C/C++ Source or Header  |  1996-02-21  |  6KB  |  232 lines

  1. /* psselect.c
  2.  * Copyright (C) Angus J. C. Duggan 1991-1995
  3.  * See file LICENSE for details.
  4.  *
  5.  * rearrange pages in conforming PS file for printing in signatures
  6.  *
  7.  * Usage:
  8.  *       psselect [-q] [-e] [-o] [-r] [-p<pages>] [infile [outfile]]
  9.  */
  10.  
  11. #include "psutil.h"
  12. #include "pserror.h"
  13. #include "patchlev.h"
  14.  
  15. char *program ;
  16. int pages ;
  17. int verbose ;
  18. FILE *infile ;
  19. FILE *outfile ;
  20. char pagelabel[BUFSIZ] ;
  21. int pageno ;
  22.  
  23. static void usage(void)
  24. {
  25.    fprintf(stderr, "%s release %d patchlevel %d\n", program, RELEASE, PATCHLEVEL);
  26.    fprintf(stderr, "Copyright (C) Angus J. C. Duggan, 1991-1995. See file LICENSE for details.\n");
  27.    fprintf(stderr,
  28.        "Usage: %s [-q] [-e] [-o] [-r] [-p<pages>] [infile [outfile]]\n",
  29.        program);
  30.    fflush(stderr);
  31.    exit(1);
  32. }
  33.  
  34. typedef struct pgrange {
  35.    int first, last;
  36.    struct pgrange *next;
  37. } PageRange ;
  38.  
  39. static PageRange *makerange(int beg, int end, PageRange *next)
  40. {
  41.    PageRange *new;
  42.    if ((new = (PageRange *)malloc(sizeof(PageRange))) == NULL)
  43.       message(FATAL, "out of memory\n");
  44.    new->first = beg;
  45.    new->last = end;
  46.    new->next = next;
  47.    return (new);
  48. }
  49.  
  50.  
  51. static PageRange *addrange(char *str, PageRange *rp)
  52. {
  53.    int first=0;
  54.    int sign;
  55.    sign = (*str == '_' && ++str) ? -1 : 1;
  56.    if (isdigit(*str)) {
  57.       first = sign*atoi(str);
  58.       while (isdigit(*str)) str++;
  59.    }
  60.    switch (*str) {
  61.    case '\0':
  62.       if (first)
  63.      return (makerange(first, first, rp));
  64.       break;
  65.    case ',':
  66.       if (first)
  67.      return (addrange(str+1, makerange(first, first, rp)));
  68.       break;
  69.    case '-':
  70.    case ':':
  71.       str++;
  72.       sign = (*str == '_' && ++str) ? -1 : 1;
  73.       if (isdigit(*str)) {
  74.      int last = sign*atoi(str);
  75.      while (isdigit(*str)) str++;
  76.      if (!first)
  77.         first = 1;
  78.      switch (*str) {
  79.      case '\0':
  80.        return (makerange(first, last, rp));
  81.      case ',':
  82.        return (addrange(str+1, makerange(first, last, rp)));
  83.      }
  84.       } else if (*str == '\0')
  85.      return (makerange(first, -1, rp));
  86.       else if (*str == ',')
  87.      return (addrange(str+1, makerange(first, -1, rp)));
  88.    }
  89.    message(FATAL, "invalid page range\n");
  90.    return (PageRange *)0 ;
  91. }
  92.  
  93.  
  94. void main(int argc, char *argv[])
  95. {
  96.    int currentpg, maxpage = 0;
  97.    int even = 0, odd = 0, reverse = 0;
  98.    int pass, all;
  99.    PageRange *pagerange = NULL;
  100.  
  101.    infile = stdin;
  102.    outfile = stdout;
  103.    verbose = 1;
  104.    for (program = *argv++; --argc; argv++) {
  105.       if (argv[0][0] == '-') {
  106.      switch (argv[0][1]) {
  107.      case 'e':    /* even pages */
  108.         even = 1;
  109.         break;
  110.      case 'o':    /* odd pages */
  111.         odd = 1;
  112.         break;
  113.      case 'r':    /* reverse */
  114.         reverse = 1;
  115.         break;
  116.      case 'p':    /* page spec */
  117.         pagerange = addrange(*argv+2, pagerange);
  118.         break;
  119.      case 'q':    /* quiet */
  120.         verbose = 0;
  121.         break;
  122.      case 'v':    /* version */
  123.      default:
  124.         usage();
  125.      }
  126.       } else if (pagerange == NULL && !reverse && !even && !odd) {
  127.      pagerange = addrange(*argv, NULL);
  128.       } else if (infile == stdin) {
  129.      if ((infile = fopen(*argv, OPEN_READ)) == NULL)
  130.         message(FATAL, "can't open input file %s\n", *argv);
  131.       } else if (outfile == stdout) {
  132.      if ((outfile = fopen(*argv, OPEN_WRITE)) == NULL)
  133.         message(FATAL, "can't open output file %s\n", *argv);
  134.       } else usage();
  135.    }
  136. #if defined(MSDOS) || defined(WINNT)
  137.    if ( infile == stdin ) {
  138.       int fd = fileno(stdin) ;
  139.       if ( setmode(fd, O_BINARY) < 0 )
  140.          message(FATAL, "can't open input file %s\n", argv[4]);
  141.     }
  142.    if ( outfile == stdout ) {
  143.       int fd = fileno(stdout) ;
  144.       if ( setmode(fd, O_BINARY) < 0 )
  145.          message(FATAL, "can't reset stdout to binary mode\n");
  146.     }
  147. #endif
  148.    if ((infile=seekable(infile))==NULL)
  149.       message(FATAL, "can't seek input\n");
  150.  
  151.    scanpages();
  152.  
  153.    /* select all pages or all in range if odd or even not set */
  154.    all = !(odd || even);
  155.  
  156.    /* add default page range */
  157.    if (!pagerange)
  158.       pagerange = makerange(1, -1, NULL);
  159.  
  160.    /* reverse page list if not reversing pages (list constructed bottom up) */
  161.    if (!reverse) {
  162.       PageRange *revlist = NULL;
  163.       PageRange *next = NULL;
  164.       while (pagerange) {
  165.      next = pagerange->next;
  166.      pagerange->next = revlist;
  167.      revlist = pagerange;
  168.      pagerange = next;
  169.       }
  170.       pagerange = revlist;
  171.    } else { /* swap start & end if reversing */
  172.       PageRange *r;
  173.       for (r = pagerange; r; r = r->next) {
  174.          int temp = r->last;
  175.          r->last = r->first;
  176.          r->first = temp;
  177.       }
  178.    }
  179.  
  180.    { /* adjust for end-relative pageranges */
  181.       PageRange *r;
  182.       for (r = pagerange; r; r = r->next) {
  183.      if (r->first < 0) {
  184.         r->first += pages + 1;
  185.         if (r->first < 0)
  186.            r->first = 0;
  187.      }
  188.      if (r->last < 0) {
  189.         r->last += pages + 1;
  190.         if (r->last < 0)
  191.            r->last = 0;
  192.      }
  193.       }
  194.    }
  195.  
  196.    /* count pages on first pass, select pages on second pass */
  197.    for (pass = 0; pass < 2; pass++) {
  198.       PageRange *r;
  199.       if (pass) {                           /* write header on second pass */
  200.      writeheader(maxpage);
  201.      writeprolog();
  202.      writesetup();
  203.       }
  204.       for (r = pagerange; r; r = r->next) {
  205.      if (r->last < r->first) {
  206.         for (currentpg = r->first; currentpg >= r->last; currentpg--) {
  207.            if (currentpg <= pages &&
  208.           ((currentpg&1) ? (odd || all) : (even || all))) {
  209.           if (pass)
  210.              writepage(currentpg-1);
  211.           else
  212.              maxpage++;
  213.            }
  214.         }
  215.      } else {
  216.         for (currentpg = r->first; currentpg <= r->last; currentpg++) {
  217.            if (currentpg <= pages &&
  218.           ((currentpg&1) ? (odd || all) : (even || all))) {
  219.           if (pass)
  220.              writepage(currentpg-1);
  221.           else
  222.              maxpage++;
  223.            }
  224.         }
  225.      }
  226.       }
  227.    }
  228.    writetrailer();
  229.  
  230.    exit(0);
  231. }
  232.